package com.basics.common.utils.weixin.accesstoken;

import com.alibaba.fastjson.JSONObject;
import com.basics.common.constant.Constants;
import com.basics.common.utils.http.HttpRequestUtil;
import com.basics.common.utils.http.SSLUtils;
import com.basics.common.utils.weixin.WxConfigConstants;
import com.basics.common.utils.weixin.model.WechatQRCode;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class WeixinGetAccessTokenUtil {


    private static final Logger logger = LoggerFactory.getLogger(WeixinGetAccessTokenUtil.class);

	// 临时二维码
	private final static String QR_SCENE = "QR_SCENE";
	// 临时二维码  (字符串)
	private final static String QR_STR_SCENE ="QR_STR_SCENE";
	// 永久二维码
	private final static String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";
	// 永久二维码(字符串)
	private final static String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";
	// 创建二维码
	private final static String create_ticket_path = "https://api.weixin.qq.com/cgi-bin/qrcode/create";
	// 通过ticket换取二维码
	public final static String showqrcode_path = "https://mp.weixin.qq.com/cgi-bin/showqrcode";

	// 获取accessToken 微信地址
    public static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    // 获取ticket  微信地址
    public static final String GET_SIGNATURE_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";

    // 获得普通操作凭证的URL
    public static final String GET_COMMON_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

    // 获取JSAPI的操作凭证URL
    public static final String GET_JSAPI_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
	/**
	 * 使用HttpClient的Get请求，从微信服务器获取access_token
	 *
	 * @return JSONObject：正确包含access_token；错误为空
	 */
	public static JSONObject doGet_getCommonAccessToken(String appid,String secret) {

		JSONObject obj = null;

		String url = GET_COMMON_ACCESS_TOKEN_URL.replace("APPID", appid)
				.replace("APPSECRET",secret);

		SSLUtils.setSSL();
		CloseableHttpClient httpClient = HttpClients.createDefault();

		HttpGet httpGet = new HttpGet(url);

		try {

			CloseableHttpResponse httpResponse = httpClient.execute(httpGet);

			String result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");

			if (result != null && !result.equals("") && result.contains("access_token")) {

				obj = JSONObject.parseObject(result);

			} else {

				obj = null;

			}

		} catch (Exception e) {

            logger.error("从微信服务器获取AccessToken错误： " + e);

		}

		return obj;

	}

	/**
	 * 通过HttpClient的Get请求，获取JSAPI_TICKET操作凭据
	 *
	 * @param accessToken：获取Jsapi_Ticket所需的access_token
	 * @return
	 */
	public static JSONObject doGet_getJsapiTicket(String accessToken) {

		JSONObject obj = null;

		String url = GET_JSAPI_ACCESS_TOKEN_URL.replace("ACCESS_TOKEN", accessToken);

		SSLUtils.setSSL();
		CloseableHttpClient httpClient = HttpClients.createDefault();

		HttpGet httpGet = new HttpGet(url);

		try {

			CloseableHttpResponse httpResponse = httpClient.execute(httpGet);

			String result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");

			if (result != null && !result.equals("") && result.contains("ticket")) {

				obj = JSONObject.parseObject(result);

			} else {

				obj = null;

			}

		} catch (Exception e) {

            logger.error("从微信服务器获取JsapiTicket错误： " + e);

		}

		return obj;

	}


	// 获取getTicket
	   public static String getTicket(String access_token){

	    String turl = String.format("%s?access_token=%s&type=jsapi",GET_SIGNATURE_URL,access_token);

		  //采用绕过验证的方式处理https请求
	        SSLUtils.setSSL();

	       CloseableHttpClient client = HttpClients.createDefault();
	       HttpGet get = new HttpGet(turl);

	       JsonParser jsonparer = new JsonParser();// 初始化解析json格式的对象
	       String result = null;
	       try
	       {
	           HttpResponse res = client.execute(get);
	           String responseContent = null; // 响应内容
	           HttpEntity entity = res.getEntity();
	           responseContent = EntityUtils.toString(entity, "UTF-8");
	           JsonObject  json= jsonparer.parse(responseContent).getAsJsonObject();
	           // 将json字符串转换为json对象
	           if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
	               if (json.get("errcode") == null){
	                // 错误时微信会返回错误码等信息，{"errcode":40013,"errmsg":"invalid appid"}
	               }
	               else{
	                // 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200}
	                   result = json.get("ticket").getAsString();
	               }
	           }
	       }
	       catch (Exception e)
	       {
	           e.printStackTrace();
	       }
	       finally
	       {
	           // 关闭连接 ,释放资源
	           client.getConnectionManager().shutdown();
	           return result;
	       }
	   }

	public static String getToken(String appid,String appsecret){

        //拼接访问地址
        String turl = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", GET_TOKEN_URL,appid, appsecret);

        CloseableHttpClient httpClient = HttpClients.createDefault();
        //get请求
        HttpGet get = new HttpGet(turl);
        // 初始化解析json格式的对象
        JsonParser jsonparer = new JsonParser();
        String result = null;
        try
        {
        	//采用绕过验证的方式处理https请求
        	SSLUtils.setSSL();

            HttpResponse res = httpClient.execute(get);
            String responseContent = null; // 初始化响应内容
            HttpEntity entity = res.getEntity();
            //设置编码格式
            responseContent = EntityUtils.toString(entity, "UTF-8");
            // 将json字符串转换为json对象
            JsonObject json = jsonparer.parse(responseContent).getAsJsonObject();
            if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
            {
                if (json.get("errcode") != null){
                    // 错误时微信会返回错误码等信息，{"errcode":40013,"errmsg":"invalid appid"}
                    }
                else{
                    // 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200}
                    result = json.get("access_token").getAsString();
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally{
            // 关闭连接 ,释放资源
        	httpClient.getConnectionManager().shutdown();
            return result;
        }
    }

	public static String getSignature(String jsapi_ticket,String url,String nonce_str,String timestamp) {
        String string1;
        String signature = "";

        // 注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str
                + "&timestamp=" + timestamp + "&url=" + url;

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }


        return signature;
    }


    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }



    /**
     * 创建永久二维码(字符串)
     *
     * @param accessToken
     * @param sceneStr 场景str
     * @return
     */
    public static String createForeverStrTicket(String accessToken, String sceneStr){
        TreeMap<String,String> params = new TreeMap<String,String>();
        params.put("access_token", accessToken);
        //output data
        Map<String,String> intMap = new HashMap<String,String>();
        intMap.put("scene_str",sceneStr);
        Map<String,Map<String,String>> mapMap = new HashMap<String,Map<String,String>>();
        mapMap.put("scene", intMap);

        Map<String,Object> paramsMap = new HashMap<String,Object>();
        paramsMap.put("action_name", QR_LIMIT_STR_SCENE);
        paramsMap.put("action_info", mapMap);
        String data = new Gson().toJson(paramsMap);
        data =  HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);
        //data = HttpRequest.httpRequest(create_ticket_path, HttpRequestUtil.POST_METHOD, data);
        WechatQRCode wxQRCode = null;
        try {
            wxQRCode = new Gson().fromJson(data, WechatQRCode.class);
        } catch (JsonSyntaxException e) {
            wxQRCode = null;
        }
        return wxQRCode==null?null:wxQRCode.getTicket();
    }


    /**
     * 创建永久二维码(数字)
     * @param accessToken
     * @param sceneId 场景Id
     * @return
     */
    public static String createForeverTicket(String accessToken, int sceneId) {

        TreeMap<String,String> params = new TreeMap<String,String>();
        params.put("access_token", accessToken);
        //output data
        Map<String,Integer> intMap = new HashMap<String,Integer>();
        intMap.put("scene_id",sceneId);
        Map<String,Map<String,Integer>> mapMap = new HashMap<String,Map<String,Integer>>();
        mapMap.put("scene", intMap);
        //
        Map<String,Object> paramsMap = new HashMap<String,Object>();
        paramsMap.put("action_name", QR_LIMIT_SCENE);
        paramsMap.put("action_info", mapMap);
        String data = new Gson().toJson(paramsMap);
        data =  HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);
        WechatQRCode wxQRCode = null;
        try {
            wxQRCode = new Gson().fromJson(data, WechatQRCode.class);
        } catch (JsonSyntaxException e) {
            wxQRCode = null;
            e.printStackTrace();
        }
        return wxQRCode==null?null:wxQRCode.getTicket();
    }

    /**
     * 创建临时二维码(字符串)
     *
     * @param accessToken
     * @param sceneStr 场景str
     * @return
     */
    public static String createSenceStrTicket(String accessToken, String sceneStr){
        TreeMap<String,String> params = new TreeMap<String,String>();
        params.put("access_token", accessToken);
        //output data
        Map<String,String> intMap = new HashMap<String,String>();
        intMap.put("scene_str",sceneStr);
        Map<String,Map<String,String>> mapMap = new HashMap<String,Map<String,String>>();
        mapMap.put("scene", intMap);

        Map<String,Object> paramsMap = new HashMap<String,Object>();
        paramsMap.put("expire_seconds", 60*60*24*3);
        paramsMap.put("action_name", QR_STR_SCENE);
        paramsMap.put("action_info", mapMap);
        String data = new Gson().toJson(paramsMap);
        data =  HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);
        //data = HttpRequest.httpRequest(create_ticket_path, HttpRequestUtil.POST_METHOD, data);
        WechatQRCode wxQRCode = null;
        try {
            wxQRCode = new Gson().fromJson(data, WechatQRCode.class);
        } catch (JsonSyntaxException e) {
            wxQRCode = null;
        }
        return wxQRCode==null?null:wxQRCode.getTicket();
    }
}
